package simulation;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import massobjects.BaseMass;
import springobjects.BaseConnector;


/**
 * An assembly made of mass and connector objects.
 * 
 * @author David Howdyshell, Zack Hopping
 * 
 */
public class Assembly {
    // state
    private List<BaseMass> myMasses;
    private List<BaseConnector> myConnectors;
    private Point2D myCenterMass;

    /**
     * Constructor initializes arrays for masses and connectors.
     */
    public Assembly () {
        myMasses = new ArrayList<BaseMass>();
        myConnectors = new ArrayList<BaseConnector>();
        myCenterMass = new Point2D.Double(0, 0);
    }

    /**
     * Adds a new mass object to the assembly.
     * 
     * @param mass - the new mass
     */
    public void add (BaseMass mass) {
        myMasses.add(mass);
    }

    /**
     * Adds a new connector to the assembly.
     * 
     * @param connector - the new connector
     */
    public void add (BaseConnector connector) {
        myConnectors.add(connector);
    }

    /**
     * Updates the center of mass of this assembly.
     */
    private void updateCenterMass () {
        double x = 0;
        double y = 0;
        int massCount = 0;
        for (BaseMass m : myMasses) {
            x += m.getCenter().getX() * m.getMass();
            y += m.getCenter().getY() * m.getMass();
            if (m.getMass() != 0) {
                massCount++;
            }
        }
        myCenterMass.setLocation(x / massCount, y / massCount);
    }

    /**
     * Gets the mass with specified ID within this assembly.
     * 
     * @param id - desired ID to find
     * @return the matching mass
     */
    public BaseMass getMass (int id) {
        for (BaseMass m : myMasses) {
            if (m.match(id)) { return m; }
        }
        return null;
    }

    /**
     * Returns pointer to list of masses.
     * 
     * @return myMasses
     */
    public List<BaseMass> getAllMasses () {
        return myMasses;
    }

    /**
     * Gets center of mass point for this assembly.
     * 
     * @return center of mass
     */
    public Point2D getCenterMass () {
        return myCenterMass;
    }

    /**
     * Calls paint for all the connectors and masses contained within this
     * assembly.
     * 
     * @param pen - object for painting!
     */
    public void paint (Graphics2D pen) {
        for (BaseConnector s : myConnectors) {
            s.paint(pen);
        }
        for (BaseMass m : myMasses) {
            m.paint(pen, Color.BLACK);
        }
    }

    /**
     * Updates center of mass and then updates all moving objects.
     * 
     * @param sim - pointer to the simulation
     * @param dt - elapsed time
     */
    public void update (Simulation sim, double dt) {
        updateCenterMass();
        updateMovers(sim, dt);
    }

    void updateMovers (Simulation sim, double dt) {
        for (BaseConnector s : myConnectors) {
            s.update(dt);
        }
        for (BaseMass m : myMasses) {
            m.update(sim, this, dt);
        }
    }
}
